#define WINDOWS 1

float4x4 World;
float4x4 View;
float4x4 Projection;

float	Alpha;					// The alpha channel of the material to be drawn.

float4	AmbientColor;			// The color of the ambient light.
float	AmbientIntensity;		// The intensity of the ambient light.

float3	DiffuseLightDirection;	// The direction of the light.
float4	DiffuseColor;			// The diffuse light color.
float	DiffuseIntensity;		// The diffuse light intensity.

float	SpecularPower;			// The "shininess" of the material. A larger value gives a small and intense specular highlight.
float4	SpecularColor;			// The color of the specular highlight.
float	SpecularIntensity;		// The intensity of the specular highlight.

float3	ViewVector;				// The direction the viewer is looking in.
float3	EyePosition;			// The position of the viewer.

float FogEnabled;
float FogStart;
float FogEnd;
float4 FogColor;

texture BasicTexture;
sampler2D textureSampler = sampler_state
{
	Texture = (BasicTexture);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

texture SpecularMap;
sampler2D specularSampler = sampler_state
{
	Texture = (SpecularMap);
	MipFilter = LINEAR;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

// TODO: add effect parameters here.

struct VertexShaderInput
{
    float4 Position				: POSITION0;
    float3 Normal				: NORMAL0;
	float2 TextureCoordinate	: TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position				: POSITION0;
    float2 TextureCoordinate	: TEXCOORD0;
    float3 Normal				: TEXCOORD1;
    float4 WorldPosition		: TEXCOORD2;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    
    output.Position = mul(viewPosition, Projection);
    output.TextureCoordinate = input.TextureCoordinate;
    output.Normal = normalize(mul(input.Normal, World));
    output.WorldPosition = worldPosition;

    return output;
}

float4 PSTextureLight(VertexShaderOutput input) : COLOR0
{
	//return float4(1,0,0,1);
	float3 N = normalize(input.Normal);
    // Calculate the diffuse light component with the bump map normal
    float diffuseIntensity = dot(normalize(DiffuseLightDirection), N);
    if(diffuseIntensity < 0.0)
        diffuseIntensity = 0.0;
       
 
    // Calculate the specular light component with the bump map normal
    float3 light = normalize(DiffuseLightDirection);
    float3 r = normalize(2 * dot(light, N) * N - light);
    float3 v = normalize(mul(normalize(ViewVector), World));
    float dotProduct = dot(r, v);
    clip(1 - dotProduct);
    float4 specular = SpecularIntensity * SpecularColor * max(pow(dotProduct, SpecularPower), 0) * diffuseIntensity;
 
    // Calculate the texture color
    float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);
    textureColor.a = Alpha;
    float fogFactor = FogEnabled * saturate((length(EyePosition-input.WorldPosition) -FogStart) /(FogEnd-FogStart)); 
	float4 color = saturate(textureColor * (diffuseIntensity + AmbientColor * AmbientIntensity) + specular);
	color.rgb = lerp(color.rgb, FogColor, fogFactor);
    return color;
}

float4 PSTextureSpecularMapLight(VertexShaderOutput input) : COLOR0
{
	//return float4(1,0,0,1);
	float3 N = normalize(input.Normal);
    // Calculate the diffuse light component with the bump map normal
    float diffuseIntensity = dot(normalize(DiffuseLightDirection), N);
    if(diffuseIntensity < 0.0)
        diffuseIntensity = 0.0;
       
 
    // Calculate the specular light component with the bump map normal
    float3 light = normalize(DiffuseLightDirection);
    float3 r = normalize(2 * dot(light, N) * N - light);
    float3 v = normalize(mul(normalize(ViewVector), World));
    float dotProduct = dot(r, v);
    clip(1 - dotProduct);
    
    float4 specularValue = tex2D(specularSampler, input.TextureCoordinate);
    float4 specular = SpecularIntensity * float4(specularValue.rgb, 1) * max(pow(dotProduct, specularValue.a * SpecularPower), 0) * diffuseIntensity;
 
    // Calculate the texture color
    float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);
    textureColor.a = Alpha;
//    float fogFactor = FogEnabled * saturate((length(EyePosition-input.WorldPosition) -FogStart) /(FogEnd-FogStart)); 
	float4 color = saturate(textureColor * (diffuseIntensity + AmbientColor * AmbientIntensity) + specular);
	//color.rgb = lerp(color.rgb, FogColor, fogFactor);
	//return float4(input.Normal, 1);
    return color;
}

float4 PSTexture(VertexShaderOutput input) : COLOR0
{
	//return float4(1,0,0,1);
    // Calculate the texture color
    float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);

    textureColor.a = Alpha;
    return textureColor;
}

float4 PSColorLight(VertexShaderOutput input) : COLOR0
{
	//return float4(1,0,0,1);
    // Calculate the diffuse light component with the bump map normal
    float diffuseIntensity = dot(normalize(DiffuseLightDirection), input.Normal);
    if(diffuseIntensity < 0.0)
        diffuseIntensity = 0.0;
 
    // Calculate the specular light component with the bump map normal
    float3 light = normalize(DiffuseLightDirection);
    float3 r = normalize(2 * dot(light, input.Normal) * input.Normal - light);
    float3 v = normalize(mul(normalize(ViewVector), World));
    float dotProduct = dot(r, v);
 
    float4 specular = SpecularIntensity * SpecularColor * max(pow(dotProduct, SpecularPower), 0) * diffuseIntensity;
 
    // Calculate the texture color
    float4 textureColor = DiffuseColor;
    textureColor.a = Alpha;
    float fogFactor = FogEnabled * saturate((length(EyePosition-input.WorldPosition) -FogStart) /(FogEnd-FogStart)); 
	float4 color = saturate((textureColor * diffuseIntensity *  (AmbientColor +AmbientIntensity)) + specular);
	color.rgb = lerp(color.rgb, FogColor, fogFactor);
	//return float4(input.Normal, 1);
    return color;
}

float4 PSColor(VertexShaderOutput input) : COLOR0
{
	//return float4(1,0,0,1);
    // Calculate the texture color
    float4 textureColor = DiffuseColor;
    textureColor.a = Alpha;
    return textureColor;
}
int PixelShaderIndex = 0;
#if WINDOWS
PixelShader pixelShaders[5] = {
	compile ps_2_0 PSTextureLight(), // Textured surfaces with lighting.
	compile ps_2_0 PSColorLight(), // Colored surfaces with lighting.
	compile ps_2_0 PSTexture(), // Textured surfaces without lighting.
	compile ps_2_0 PSColor(), // Colored surfaces without lighting.
	compile ps_2_0 PSTextureSpecularMapLight(), // Textured surfares with lighting and specular maps.	
};
#endif


technique Technique1
{
    pass Pass1
    {
        // TODO: set renderstates here.

        VertexShader = compile vs_2_0 VertexShaderFunction();
        #if WINDOWS
        PixelShader = (pixelShaders[PixelShaderIndex]);
        #else
        PixelShader = compile ps_2_0 PSTextureLight();
        #endif
    }
}
